import * as THREE from "three"
import bmfont from "layout-bmfont-text"

var t = { min: [0, 0], max: [0, 0] }
function i(e) {
  var i = e.length / 2
  ;(t.min[0] = e[0]), (t.min[1] = e[1]), (t.max[0] = e[0]), (t.max[1] = e[1])
  for (var n = 0; n < i; n++) {
    var s = e[2 * n + 0],
      r = e[2 * n + 1]
    ;(t.min[0] = Math.min(s, t.min[0])), (t.min[1] = Math.min(r, t.min[1])), (t.max[0] = Math.max(s, t.max[0])), (t.max[1] = Math.max(r, t.max[1]))
  }
}
const computeBox = function (e, n) {
  i(e), n.min.set(t.min[0], t.min[1], 0), n.max.set(t.max[0], t.max[1], 0)
}
const computeSphere = function (e, n) {
  i(e)
  var s = t.min[0],
    r = t.min[1],
    o = t.max[0] - s,
    a = t.max[1] - r,
    l = Math.sqrt(o * o + a * a)
  n.center.set(s + o / 2, r + a / 2, 0), (n.radius = l / 2)
}

const pages = function (e) {
  var t = new Float32Array(4 * e.length * 1),
    i = 0
  return (
    e.forEach(function (e) {
      var n = e.data.page || 0
      ;(t[i++] = n), (t[i++] = n), (t[i++] = n), (t[i++] = n)
    }),
    t
  )
}
const uvs = function (e, t, i, n) {
  var s = new Float32Array(4 * e.length * 2),
    r = 0
  return (
    e.forEach(function (e) {
      var o = e.data,
        a = o.x + o.width,
        l = o.y + o.height,
        c = o.x / t,
        h = o.y / i,
        d = a / t,
        u = l / i
      n && ((h = (i - o.y) / i), (u = (i - l) / i)),
        (s[r++] = c),
        (s[r++] = h),
        (s[r++] = c),
        (s[r++] = u),
        (s[r++] = d),
        (s[r++] = u),
        (s[r++] = d),
        (s[r++] = h)
    }),
    s
  )
}
const positions = function (e) {
  var t = new Float32Array(4 * e.length * 2),
    i = 0
  return (
    e.forEach(function (e) {
      var n = e.data,
        s = e.position[0] + n.xoffset,
        r = e.position[1] + n.yoffset,
        o = n.width,
        a = n.height
      ;(t[i++] = s), (t[i++] = r), (t[i++] = s), (t[i++] = r + a), (t[i++] = s + o), (t[i++] = r + a), (t[i++] = s + o), (t[i++] = r)
    }),
    t
  )
}

import funcUtil from "../utils/func.util"

var toString = Object.prototype.toString
function isArray(e) {
  return (e.BYTES_PER_ELEMENT && "[object ArrayBuffer]" === toString.call(e.buffer)) || Array.isArray(e)
}
function isBuffer(e) {
  return !!e.constructor && "function" == typeof e.constructor.isBuffer && e.constructor.isBuffer(e)
}

function canBuffer(e) {
  return (
    null != e &&
    (isBuffer(e) ||
      (function (e) {
        return "function" == typeof e.readFloatLE && "function" == typeof e.slice && isBuffer(e.slice(0, 0))
      })(e) ||
      !!e._isBuffer)
  )
}

var o = [0, 2, 3],
  a = [2, 1, 3]
function getIndex(e, t) {
  ;(e && (isArray(e) || canBuffer(e))) || ((t = e || {}), (e = null))
  for (
    var i = "string" == typeof (t = "number" == typeof t ? { count: t } : t || {}).type ? t.type : "uint16",
      l = "number" == typeof t.count ? t.count : 1,
      c = t.start || 0,
      h = !1 !== t.clockwise ? o : a,
      d = h[0],
      u = h[1],
      p = h[2],
      m = 6 * l,
      g = e || new (funcUtil.numberType(i))(m),
      f = 0,
      v = 0;
    f < m;
    f += 6, v += 4
  ) {
    var y = f + c
    ;(g[y + 0] = v + 0), (g[y + 1] = v + 1), (g[y + 2] = v + 2), (g[y + 3] = v + d), (g[y + 4] = v + u), (g[y + 5] = v + p)
  }
  return g
}

export default class TextGeometry extends THREE.BufferGeometry {
  _opt: any
  layout: any
  visibleGlyphs: any
  constructor(e) {
    super()
    this.type = "TextGeometry"
    "string" == typeof e && (e = { text: e })
    this._opt = Object.assign({}, e)
    e && this.update(e)
  }
  update(e) {
    if (("string" == typeof e && (e = { text: e }), !(e = Object.assign({}, this._opt, e)).font)) throw new TypeError("must specify a { font } in options")
    this.layout = bmfont(e)
    var t = !1 !== e.flipY,
      i = e.font,
      o = i.common.scaleW,
      a = i.common.scaleH,
      l = this.layout.glyphs.filter(function (e) {
        var t = e.data
        return t.width * t.height > 0
      })
    this.visibleGlyphs = l
    var c = positions(l),
      h = uvs(l, o, a, t),
      d = getIndex([], { clockwise: !0, type: "uint16", count: l.length })
    if (
      (this.setIndex(d),
      this.setAttribute("position", new THREE.BufferAttribute(c, 2)),
      this.setAttribute("uv", new THREE.BufferAttribute(h, 2)),
      !e.multipage && "page" in this.attributes)
    )
      this.removeAttribute("page")
    else if (e.multipage) {
      var u = pages(l)
      this.setAttribute("page", new THREE.BufferAttribute(u, 1))
    }
  }
  computeBoundingSphere() {
    null === this.boundingSphere && (this.boundingSphere = new THREE.Sphere())
    var e = this.attributes.position.array,
      t = this.attributes.position.itemSize
    if (!e || !t || e.length < 2) return (this.boundingSphere.radius = 0), void this.boundingSphere.center.set(0, 0, 0)
    computeSphere(e, this.boundingSphere),
      isNaN(this.boundingSphere.radius) &&
        console.error('THREE.BufferGeometry.computeBoundingSphere():\nComputed radius is NaN. The\n"position" attribute is likely to have NaN values.')
  }
  computeBoundingBox() {
    null === this.boundingBox && (this.boundingBox = new THREE.Box3())
    var e = this.boundingBox,
      t = this.attributes.position.array,
      i = this.attributes.position.itemSize
    !t || !i || t.length < 2 ? e.makeEmpty() : computeBox(t, e)
  }
}
